// Text of project SoupDrink written on 5/27/96 at 11:00
// Beginning of file protoEvent

// Before Script for "_userproto000"
//	Newton Developer Technical Support Sample Code
//	protoEvent - An NTK Finite State Machine User Proto
//	by Jim Schram, Newton Developer Technical Support
//	Copyright 1996 Apple Computer, Inc.  All rights reserved.
//	
//	You may incorporate this sample code into your applications without
//	restriction.  This sample code has been provided "AS IS" and the
//	responsibility for its operation is 100% yours.  You are not
//	permitted to modify and redistribute the source as "DTS Sample Code."
//	If you are going to re-distribute the source, we require that you
//	make it clear in the source that the code was descended from
//	Apple-provided sample code, but that you've made changes.


_userproto000 :=
    {viewBounds: {left: 8, top: 16, right: 96, bottom: 32}, _proto: @218};


constant |layout_protoEvent| := _userproto000;
// End of file protoEvent
// Beginning of file protoState

// Before Script for "_userproto001"
//	Newton Developer Technical Support Sample Code
//	protoState - An NTK Finite State Machine User Proto
//	by Jim Schram, Newton Developer Technical Support
//	Copyright 1996 Apple Computer, Inc.  All rights reserved.
//	
//	You may incorporate this sample code into your applications without
//	restriction.  This sample code has been provided "AS IS" and the
//	responsibility for its operation is 100% yours.  You are not
//	permitted to modify and redistribute the source as "DTS Sample Code."
//	If you are going to re-distribute the source, we require that you
//	make it clear in the source that the code was descended from
//	Apple-provided sample code, but that you've made changes.


_userproto001 :=
    {viewBounds: {left: 8, top: 16, right: 112, bottom: 56}, _proto: @473};


constant |layout_protoState| := _userproto001;
// End of file protoState
// Beginning of file protoFSM

// Before Script for "_userproto002"
//	Newton Developer Technical Support Sample Code
//	protoFSM - An NTK Finite State Machine User Proto
//	by Jim Schram, Newton Developer Technical Support
//	Copyright 1996 Apple Computer, Inc.  All rights reserved.
//	
//	You may incorporate this sample code into your applications without
//	restriction.  This sample code has been provided "AS IS" and the
//	responsibility for its operation is 100% yours.  You are not
//	permitted to modify and redistribute the source as "DTS Sample Code."
//	If you are going to re-distribute the source, we require that you
//	make it clear in the source that the code was descended from
//	Apple-provided sample code, but that you've made changes.

kFSMCleanUpFunc := func(fsmFrame)
begin
	local fsmSymbol, stateSymbol, eventSymbol, hasGenesisState;
	
	RemoveSlot(fsmFrame._proto, '_proto);
	RemoveSlot(fsmFrame._proto, 'viewBounds);
	RemoveSlot(fsmFrame, 'viewBounds);
	
	fsmFrame.fsm_private_states := {	};
	
	if not fsmSymbol := GetSlot(fsmFrame, 'declareSelf) then
		begin
			fsmSymbol := 'unknown;
			print("A protoFSM implementation is unnamed (you forgot the declareSelf slot).");
		end;
	
	if fsmFrame.stepChildren then
		foreach stateFrame in fsmFrame.stepChildren do
			begin
				RemoveSlot(stateFrame, '_proto);
				RemoveSlot(stateFrame, 'viewBounds);
				
				if not stateSymbol := GetSlot(stateFrame, 'declareSelf) then
					begin
						stateSymbol := 'unknown;
						print("A protoState in the '|" & fsmSymbol & "| protoFSM implementation is unnamed (you forgot the declareSelf slot).");
					end;
				if fsmFrame.fsm_private_states.(stateSymbol) then
					print("The '|" & stateSymbol & "| protoState in the '|" & fsmSymbol & "| protoFSM implementation already exists (duplicate declareSelf slot value).");
				else
					fsmFrame.fsm_private_states.(stateSymbol) := stateFrame;
				
				if stateFrame.stepChildren then
					foreach eventFrame in stateFrame.stepChildren do
						begin
							RemoveSlot(eventFrame, '_proto);
							RemoveSlot(eventFrame, 'viewBounds);
							
							if not eventSymbol := GetSlot(eventFrame, 'declareSelf) then
								begin
									eventSymbol := 'unknown;
									print("A protoEvent in the '|" & stateSymbol & "| state of the '|" & fsmSymbol & "| protoFSM implementation is unnamed (you forgot the declareSelf slot).");
								end;
							if stateFrame.(eventSymbol) then
								print("The '|" & eventSymbol & "| protoEvent in the '|" & stateSymbol & "| protoState in the '|" & fsmSymbol & "| protoFSM implementation already exists (duplicate declareSelf slot value).");
							else
								stateFrame.(eventSymbol) := eventFrame;
							
							RemoveSlot(eventFrame, 'declareSelf);
						end;
				
				RemoveSlot(stateFrame, 'declareSelf);
				RemoveSlot(stateFrame, 'stepChildren);
				
				hasGenesisState := hasGenesisState or stateSymbol = 'Genesis;
			end;
	
	if not hasGenesisState then
		print("The '|" & fsmSymbol & "| protoFSM implementation is missing the required '|Genesis| state.");
	
	if not kDebugOn then		// GoToState is a debug-only function!
		begin
			RemoveSlot(fsmFrame._proto, 'GoToState);
			RemoveSlot(fsmFrame, 'GoToState);
		end;
	RemoveSlot(fsmFrame, 'stepChildren);
end

_userproto002 :=
    {viewBounds: {left: 8, top: 8, right: 128, bottom: 72},
     DoEvent:
       func(eventSymbol, paramArray)	// SELF can be anything that inherits to the finite state machine instance frame
       begin
       	local x := fsm_private_context;
       	if not x then		// this catches the situation where the FSM is disposed before a pending delayed action/call/send executes
       		return;
       	
       	if kDebugOn then
       		if paramArray and PrimClassOf(paramArray) <> 'Array then
       			Throw('|evt.ex.msg|, "protoFSM:DoEvent 2nd argument must be Nil or Array");
       	
       	x.pendingEventQueue:EnQueue(eventSymbol);
       	x.pendingParamsQueue:EnQueue(paramArray);
       	
       	if not x.busy then
       		begin
       			x.busy := true;
       			AddDelayedSend(x.fsm, 'DoEvent_Loop, nil, x.turtle);
       		end;
       	
       	nil;
       end,
     Instantiate:
       //	SELF is the finite state machine template frame, e.g.:
       //
       //	local fsm := GetLayout("myFSM"):Instantiate();
       //
       //	"myFSM" is assumed to be a layout based on protoFSM,
       
       func()
       begin
       	local obj := {	_proto:							self,
       						fsm:								nil,
       						currentStateFrame:		nil,
       						currentEventFrame:		nil,
       						fsm_private_context:	{	fsm:								nil,
       																turtle:							1,
       																level:							0,
       																busy:							nil,
       																waitView:						nil,
       																waitAborted:				nil,
       																isNewPendingState:		true,
       																pendingState:				'Genesis,
       																pendingEventQueue:		QueueTemplate:Instantiate(),
       																pendingParamsQueue:	QueueTemplate:Instantiate(),
       																currentState:				nil,
       																currentEvent:				nil,
       																currentParams:			nil,	},	};
       	obj.currentStateFrame := {	_proto:		obj.fsm_private_states.Genesis,
       												_parent:	obj,	};
       	obj.fsm := obj.fsm_private_context.fsm := obj;
       end,
     Dispose:
       func()	// SELF is the finite state machine instance frame
       begin
       	fsm_private_context.pendingEventQueue:Reset();
       	fsm_private_context.pendingParamsQueue:Reset();
       	foreach slot in fsm_private_context do fsm_private_context.slot := nil;
       	currentStateFrame := currentEventFrame := fsm_private_context := nil;		// guaranteed to return nil so that the caller can conveniently nil out the FSM container variable
       end,
     DoEvent_Loop:
       func()	// SELF is the finite state machine instance frame
       begin
       	local x := fsm_private_context;
       	if not x then		// this catches the situation where the FSM is disposed before a pending delayed action/call/send executes
       		return;
       	
       	local ok;
       	local pendingStateFrame;
       	
       	if x.pendingState then
       		if fsm_private_states.(x.pendingState) then
       			if fsm_private_states.(x.pendingState).(x.pendingEventQueue:Peek()) then
       				ok := true;
       			else
       				begin
       					if kDebugOn then :?DebugFSM('UnknownEvent, x.pendingState, x.pendingEventQueue:Peek(), x.pendingParamsQueue:Peek());			// ignore if event not programmed
       				end;
       		else
       			begin
       				if kDebugOn then :?DebugFSM('UnknownState, x.pendingState, x.pendingEventQueue:Peek(), x.pendingParamsQueue:Peek());			// error --> remain in current state
       			end;
       	else
       		begin
       			if kDebugOn then :?DebugFSM('NilState, x.pendingState, x.pendingEventQueue:Peek(), x.pendingParamsQueue:Peek());					// machine halted
       		end;
       	
       	if not ok then
       		begin
       			currentStateFrame := nil;
       			currentEventFrame := nil;
       			
       			x.pendingEventQueue:DeQueue();		// there is a problem with this state or event
       			x.pendingParamsQueue:DeQueue();		// so remove the offending pending queue elements
       		end;
       	else
       		begin
       			x.currentState := x.pendingState;
       			x.currentEvent := x.pendingEventQueue:DeQueue();
       			x.currentParams := x.pendingParamsQueue:DeQueue();
       			
       			if x.isNewPendingState then
       				begin
       					x.isNewPendingState := nil;
       					currentStateFrame :=	{	_proto:		fsm_private_states.(x.currentState),
       															_parent:	self,	};
       				end;
       			
       			currentEventFrame :=	{	_proto:		fsm_private_states.(x.currentState).(x.currentEvent),
       													_parent:	currentStateFrame,	};
       			
       			if currentEventFrame.Action then
       				begin
       					if kDebugOn then :?TraceFSM('PreAction, x.currentState, x.currentEvent, x.currentParams);
       					
       					x.level := x.level + 1;
       					try
       						Perform(currentEventFrame, 'Action, x.currentParams);
       					onexception |evt.ex| do
       						begin
       							try
       								:?ExceptionHandler(CurrentException());
       							onexception |evt.ex| do
       								nil;
       						end;
       					x.level := x.level - 1;
       					
       					if kDebugOn then :?TraceFSM('PostAction, x.currentState, x.currentEvent, x.currentParams);
       				end;
       			
       			if currentEventFrame.nextState then
       				begin
       					x.pendingState := currentEventFrame.nextState;
       					x.isNewPendingState := (x.currentState <> x.pendingState);
       				end;
       			
       			if kDebugOn then :?TraceFSM('NextState, x.pendingState, x.pendingEventQueue:Peek(), x.pendingParamsQueue:Peek());
       		end;
       	
       	if x.waitView												// check for terminal state & exit waitView if necessary
       	and x.pendingState
       	and pendingStateFrame := fsm_private_states.(x.pendingState) then
       		if pendingStateFrame.terminal then
       			begin
       				x.pendingEventQueue:Reset();
       				x.pendingParamsQueue:Reset();
       				AddDelayedCall(	func()
       											if x.waitView then
       												x.waitView:Close(), nil, 1	);
       			end;
       
       	if x.pendingEventQueue:IsEmpty() then
       		x.busy := nil;
       	else
       		AddDelayedSend(self, 'DoEvent_Loop, nil, x.turtle);
       	
       	nil;
       end,
     SetSpeed:
       func(newSpeed)		// SELF is the finite state machine instance frame
       begin
       	fsm_private_context.turtle := newSpeed;
       end,
     IsBusy:
       func()	// SELF is the finite state machine instance frame
       begin
       	fsm_private_context.busy;
       end,
     GetSpeed:
       func()	// SELF is the finite state machine instance frame
       begin
       	fsm_private_context.turtle;
       end,
     GoToState:
       // SELF is the finite state machine instance frame
       // This function is for DEBUGGING USE ONLY ! ! !
       // It is STRIPPED from the resulting package when kDebugOn = nil
       
       func(newState)
       begin
       	local x := fsm_private_context;
       	
       	x.pendingState := newState;
       	x.pendingEventQueue:Reset();
       	x.pendingParamsQueue:Reset();
       	
       	nil;
       end,
     QueueTemplate:
       {
       	Instantiate:			func()									// This is a very simple First-In-First-Out queue
       								{	_proto:		self,
       									queue:		[],	},
       	
       	Reset:					func() SetLength(queue, 0),
       	
       	Peek:					func() if Length(queue) > 0 then queue[0],		// else nil
       	
       	DeQueue:				func()
       								if Length(queue) > 0 then		// else nil
       									begin
       										local data := queue[0];
       										RemoveSlot(queue, 0);
       										data;
       									end,
       	
       	EnQueue:				func(data)
       								begin
       									AddArraySlot(queue, data);
       									nil;
       								end,
       	
       	GetQueueSize:		func() Length(queue),
       	
       	IsEmpty:				func() Length(queue) = 0,
       },
     ProtoClone:
       func(object)
       begin
       	local f := 
       		func native(obj)
       		begin
       			if not IsFrame(obj) or IsFunction(obj) then
       				Throw('|evt.ex.msg|, "ProtoClone only works with frames.");
       			
       			local new := {_proto: obj};
       			foreach slot, value in obj do
       				if IsFrame(value) and not IsFunction(value) then
       					new.(slot) := call f with (value);
       			new;
       		end;
       	
       	call f with (object);
       end,
     WaitForTerminal:
       func(options)
       begin
       	local x := fsm_private_context;
       	
       	if x.waitView
       	or x.level <> 0
       	or x.pendingEventQueue:IsEmpty() then
       		return;
       	
       	x.waitView := BuildContext(waitViewTemplate);
       	x.waitView:SetOwnerContext(x, options);
       	x.waitView:ModalDialog();
       	x.waitAborted;		// return the value of waitAborted (true = user aborted via the status slip, nil = FSM terminal state was reached normally)
       end,
     waitViewTemplate:
       {	viewClass:					clView,
       	viewFlags:					vVisible,
       	viewFormat:					vfNone,
       	viewBounds:					{	left:			0,
       											top:			0,
       											right:		0,
       											bottom:		0,	},
       	
       	statusView:					nil,
       	statusViewOptions:		nil,
        	fsmContext:					nil,
        	aborted:						nil,
        	
       	SetOwnerContext:			func(owner, options)
       										begin
       											self.statusView := nil;
       											self.statusViewOptions := options;		// frame of options the caller of WaitForTerminal is passing us (e.g.  progress messages, etc.)
       											self.fsmContext := owner;				// the fsm_private_context slot of the FSM
       											self.aborted := nil;
       										end,
       	
       	viewIdleScript:				func()
       										begin
       											statusView := BuildContext(statusViewTemplate);
       											statusView:SetOwnerContext(self, statusViewOptions);
       											statusView:ModalDialog();
       											nil;
       										end,
       	
       	viewSetupDoneScript:	func()
       										begin
       											inherited:?ViewSetupDoneScript();
       											if not statusViewOptions then
       												:SetUpIdle(2000);
       											else if statusViewOptions.delayUntilStatusVisible then
       												:SetUpIdle(if statusViewOptions.delayUntilStatusVisible <= 0 then 1 else statusViewOptions.delayUntilStatusVisible);
       										end,
       	
       	viewQuitScript:			func()
       										begin
       											if statusView then
       												statusView:Close();
       											fsmContext.waitAborted := aborted;
       											fsmContext.waitView := nil;
       										end,
       	
       	statusViewTemplate:		{	_proto:								protoStatusTemplate,
       											initialSetup:						nil,
       											waitView:							nil,
       											delayUntilAbortTimer:		nil,
       											delayUntilAbortVisible:		nil,
       											abortButtonText:				nil,
       											
       											viewIdleScript:					func()
       																					begin
       																						inherited:?viewIdleScript();
       																						local contents :=	{	name:		'vBarber,
       																														values:		{	barber:		true,	},	};
       																						
       																						if delayUntilAbortVisible then
       																							begin
       																								delayUntilAbortTimer := delayUntilAbortTimer + 300;
       																								if delayUntilAbortTimer > delayUntilAbortVisible then
       																									begin
       																										delayUntilAbortVisible := nil;
       																										contents.values.primary := {	text:			abortButtonText,
       																																					script:		func()
       																																									begin
       																																										waitView.aborted := true;
       																																										waitView:Close();
       																																									end,	};
       																										base:ViewSet(contents);
       																										return 300;
       																									end;
       																							end;
       																						
       																						base:UpdateIndicator(contents);
       																						300;
       																					end,
       											
       											viewSetupDoneScript:		func()
       																					begin
       																						inherited:?ViewSetupDoneScript();
       																						:SetUpIdle(100);
       																						self.delayUntilAbortTimer := 0;
       																					end,
       											
       											SetOwnerContext:				func(owner, options)
       																					begin
       																						self.waitView := owner;
       																						self.delayUntilAbortVisible := if options then options.delayUntilAbortVisible else 8000;
       																						self.abortButtonText := if options and options.abortButtonText then options.abortButtonText else "Abort";
       												     									self.initialSetup := {	name:		'vBarber, 
       																														values:		{	icon:					ROM_routeUpdateBitmap,
       																																			statusText:		if options then options.statusText else "Please wait...",
       																																			titleText:			if options then options.titleText else nil,
       																																			barber:				true,
       																																			primary:			nil,
       																																			closeBox:			nil,	},	};
       												     								end,
       										},
       },
     ExceptionHandler:
       func(exception)
       begin
       	local x := fsm_private_context;
       	local message :=	if x then
       									"The following exception occured in event ("
       									& x.currentEvent
       									& ") of state ("
       									& x.currentState
       									& ") of finite state machine ("
       									& x.fsm.declareSelf
       									& "):  "
       								else
       									"The following exception occured:  ";
       	
       	local exceptionStr := "<unable to create string representation of exception frame>";
       	try
       		exceptionStr := :ObjectToString(exception);
       	onexception |evt.ex| do
       		nil;
       	
       	GetRoot():Notify(kNotifyAlert, kAppName, message & exceptionStr);
       	
       	print(message);
       	print(exception);
       	if GetGlobalVar('BreakOnThrows) then
       		BreakLoop();
       	
       	nil;
       end,
     ObjectToString:
       // Converts almost any NewtonScript data type into a string representation.
       // Does NOT handle recursive/self-referencing frames.
       // Does NOT follow _proto & _parent pointers.
       // Does NOT check for out-of-memory conditions, bad object refs, et cetera.
       
       func(obj)
       begin
       	local separator := ", ";
       	local separatorLen := StrLen(separator);
       	
       	local p :=
       		func(s)
       		if EndsWith(s, separator) then
       			StrMunger(s, StrLen(s) - separatorLen, nil, nil, 0, nil)
       		else
       			s;
       	
       	local f :=
       		func(obj)
       		begin
       			(	if IsFunction(obj) then
       					"func(" & NumberStr(GetFunctionArgCount(obj)) & (if GetFunctionArgCount(obj) = 1 then " arg)" else " args)")
       				
       				else if IsFrame(obj) then
       					begin
       						local s := "{";
       						foreach slot, item in obj do
       							s := s & SPrintObject(slot) & ": " & 
       								if slot = '_parent or slot = '_proto then
       									"<ignored>" & separator
       								else
       									call f with (item);
       						call p with (s) & "}";
       					end
       				
       				else if IsArray(obj) then
       					begin
       						local s := "[";
       						foreach item in obj do
       							s := s & call f with (item);
       						call p with (s) & "]";
       					end
       				
       				else if IsString(obj) then
       					$" & obj & $"
       				
       				else if IsSymbol(obj) then
       					$' & obj
       				
       				else if IsNumber(obj) or IsInteger(obj) then
       					NumberStr(obj)
       				
       				else if IsImmediate(obj) then
       					if not obj then
       						"nil"
       					else if obj = true then
       						"true"
       					else
       						SPrintObject(obj)
       				
       				else
       					SPrintObject(obj)
       			
       			) & separator;
       		end;
       	
       	call p with (call f with (obj));
       end,
     _proto: @218
    };


constant |layout_protoFSM| := _userproto002;
// End of file protoFSM
// Beginning of file DrinkFSM

// Before Script for "Drink FSM"
//	Newton Developer Technical Support Sample Code
//	DrinkFSM - An NTK Finite State Machine Implementation
//	by Jim Schram, Newton Developer Technical Support
//	Copyright 1996 Apple Computer, Inc.  All rights reserved.
//	
//	You may incorporate this sample code into your applications without
//	restriction.  This sample code has been provided "AS IS" and the
//	responsibility for its operation is 100% yours.  You are not
//	permitted to modify and redistribute the source as "DTS Sample Code."
//	If you are going to re-distribute the source, we require that you
//	make it clear in the source that the code was descended from
//	Apple-provided sample code, but that you've made changes.


Drink FSM :=
    {viewBounds: {left: 0, top: 0, right: 496, bottom: 496},
     DebugFSM:
       func(reason, state, event, params)
       begin
       	local s :=	"Reason = " & :ObjectToString(reason)
       					& "\nState = " & :ObjectToString(state)
       					& "\nEvent = " & :ObjectToString(event)
       					& "\nParams = " & :ObjectToString(params);
       	
       	:MTrace(s);
       	print(SubstituteChars(s, "\n", "\t"));
       end,
     TraceFSM:
       func(when, state, event, params)
       begin
       	local s :=	"When = " & :ObjectToString(when)
       					& "\nState = " & :ObjectToString(state)
       					& "\nEvent = " & :ObjectToString(event)
       					& "\nParams = " & :ObjectToString(params);
       	
       	:MTrace(s);
       	print(SubstituteChars(s, "\n", "\t"));
       end,
     MNotifyError:
       // where = string describing location of error
       // error = NewtonScript object (e.g. integer, real number, exception frame, etc.) describing the error
       
       func(where, error)
       begin
       	if not error
       	or error = -16005
       	or fQuiet then
       		return;
       	
       	:MNotify("An error occured in " & where & ".  Error = " & :ObjectToString(error));
       end,
     MNotify:
       func(message)
       begin
       	GetRoot():Notify(kNotifyAlert, kAppName, message);
       end,
     MTrace:
       func(s)
       begin
       	if call kViewIsOpenFunc with (GetRoot().(kAppSymbol)) then
       		begin
       			SetValue(GetRoot().(kAppSymbol).vTraceBox, 'text, s);
       			RefreshViews();
       		end;
       end,
     fState: nil,
     fConnectAction: nil,
     fEndpoint: nil,
     fPowerOffState: nil,
     declareSelf: 'DrinkFSM,
     fQuiet: nil,
     fConnectType: 'ADSP,
     fConnectAddress: nil,
     fFrameCount: 0,
     fSoup: nil,
     fSoupEntry: nil,
     fSoupCursor: nil,
     debug: "Drink FSM",
     _proto: _userproto002
    };

Genesis :=
    {viewBounds: {left: 8, top: 16, right: 112, bottom: 56},
     terminal: true,
     declareSelf: 'Genesis,
     debug: "Genesis",
     _proto: _userproto001
    };
AddStepForm(Drink FSM, Genesis);

Instantiate :=
    {viewBounds: {left: 8, top: 16, right: 96, bottom: 32},
     Action:
       func(connectType, connectAddress)
       begin
       	// Initialize the FSM.
       	fsm.fConnectAction := 'Connect;
       	fsm.fConnectType := connectType;
       	fsm.fConnectAddress := connectAddress;
       	
       	// fState is not the state of the FSM, it represents the state of the Drink protocol.
       	fsm.fState := 'Connecting;
       	fsm.fPowerOffState := nil;
       	fsm.fQuiet := nil;
       	fsm.fEndpoint := {	_proto:		fEndpointSpec,
       								_parent:	fsm,	};
       	
       	RegPowerOff(	kAppSymbol,
       							func(what, why)			// we create the closure here so as to set up SELF as the event frame in the closure
       							begin
       								if what = 'okToPowerOff then
       									begin
       										if why <> 'idle							// keep the unit awake whenever we're connected
       										or fsm.fState = 'Disconnected then		// unless the user or an application explicitly
       											return true;						// wants it to sleep
       									end;
       								
       								else if what = 'powerOff then
       									begin
       										if why <> 'idle									// if we simply must go to sleep but we're still
       										or fsm.fState <> 'Disconnected then				// connected then begin the disconnect process
       											begin
       												fsm.fPowerOffState := 'holdYourHorses;	// set a flag to indicate we're powering down
       												:DoEvent('PowerOff, nil);
       												return 'holdYourHorses;
       											end;
       									end;
       								
       								nil;	// ALWAYS return nil here!
       							end	);
       	
       	fsm.fSoup := nil;
       	fsm.fSoupCursor := nil;
       	fsm.fSoupEntry := nil;
       	
       	// Bring up the endpoint
       	:DoEvent('Instantiate, nil);
       end,
     nextState: 'Instantiate,
     declareSelf: 'Create,
     fEndpointSpec:
       {
       	_proto:		protoBasicEndpoint,
       	
       	exceptionHandler:	func(exception)
       								begin
       									if exception.data <> -16005
       									and exception.data <> -38001 then
       										:MNotifyError("Endpoint Exception Handler", exception);
       								end,
       	
       	// InputSpec for command handling
       	fInputCommand:
       		{	form:					'string,
       			termination:			{	endSequence:	[unicodeEOT],	},
       			discardAfter:		256,
       			inputScript:			func(ep, data, terminator, options)
       										begin								            
       											if BeginsWith(data, "DRNK") then
       												ep:DoEvent('DrinkBegin, [data]);
       											
       											else if BeginsWith(data, "OK") then
       												ep:DoEvent('DrinkNextEntry, nil);
       											
       											else if BeginsWith(data, "HELO") then
       												ep:DoEvent('HelloBegin, [data]);
       											
       											else if BeginsWith(data, "NAME") then
       												begin
       													ep:DoEvent('NameBegin, [data]);
       													ep:SetInputSpec(ep.fInputFrame);
       												end;
       											
       											else
       												// This should never happen.
       												ep:DoEvent('Unknown, [data]);
       										end,
       			completionScript:	func(ep, options, result)
       										begin
       											// Cancelled calls may raise either -10039 or -16005, ignore them.
       											if result
       											and result <> -10039
       											and result <> -16005 then
       												ep:DoEvent('InputFailure, [result]);
       										end
       		},
       	
       	fInputFrame:
       		{	form:					'frame,
       	      	inputScript:			func(ep, data, terminator, options)
       								     	begin
       								        	ep:DoEvent('NameAdd, [data]);
       								    	end,
       			completionScript:	func(ep, options, result)
       										begin
       											// Cancelled calls may raise either -10039 or -16005, ignore them.
       											if result
       											and result <> -10039
       											and result <> -16005 then
       												ep:DoEvent('InputFailure, [result]);
       										end
       		},
       },
     debug: "Instantiate",
     _proto: _userproto000
    };
AddStepForm(Genesis, Instantiate);





Instantiate :=
    {viewBounds: {left: 120, top: 16, right: 224, bottom: 120},
     declareSelf: 'Instantiate,
     debug: "Instantiate",
     _proto: _userproto001
    };
AddStepForm(Drink FSM, Instantiate);

Instantiate :=
    {viewBounds: {left: 8, top: 16, right: 96, bottom: 32},
     Action:
       func()
       begin
       	try
       		fEndpoint:Instantiate(fEndpoint, :MBuildConfigOptions(fConnectType));
       	onexception |evt.ex| do
       		return :DoEvent('InstantiateFailure, [CurrentException()]);
       	
       	:DoEvent('InstantiateSuccess, nil);
       end,
     declareSelf: 'Instantiate,
     MBuildConfigOptions:
       func(connectionType)
       begin
       	if connectionType = 'ADSP then
       		[
       			{	label:		kCMSAppleTalkID,
       				type:		'service,
       				opCode:		opSetRequired,	},
       			
       			{ 	label:		kCMSAppleTalkID,
       				type:		'option,
       				opCode:		opSetRequired,
       				data:		{
       					arglist:		[ 
       						"adsp",	],
       					typelist:	['struct,
       						['array, 'char, 4],	],	},	},
       			
       			{	label:		kCMOEndpointName,
       				type:		'option,
       				opCode:		opSetRequired,
       				data:		{
       					arglist:		[
       						kADSPEndpoint,		],
       					typeList:	['struct, 
       						[11, 13, 0],	],	},	},
       		]
       	else
       		[
       			{	label:		kCMSMNPID,
       				type:		'service,
       				opCode:		opSetRequired,	},
       			
       			{	label:		kCMOSerialIOParms,
       				type:		'option,
       				opCode:		opSetRequired,
       				result:		nil,
       				form:		'template,
       				data:	{
       					arglist:	[
       						k1StopBits,				// 1 stop bit
       						kNoParity,				// no parity bit
       						k8DataBits,				// 8 data bits
       						k38400bps,	],			// date rate in bps
       					typelist:	['struct,
       						'long,						// stop bits
       						'long,						// parity
       						'long,						// data bits
       						'long,	],	},	},			// bps
       			
       			{	label:		kCMOMNPDataRate,
       				type:		'option,
       				opCode:		opSetRequired,
       				form:		'number,
       				data:			k38400bps,	},
       			
       			{	label:		kCMOMNPCompression,
       				type:		'option,
       				opCode:		opSetNegotiate,
       				form:		'number,
       				data:			kMNPCompressionV42bis + kMNPCompressionMNP5 + kMNPCompressionNone,	},
       		];
       end,
     debug: "Instantiate",
     _proto: _userproto000
    };
AddStepForm(Instantiate, Instantiate);



Instantiate Success :=
    {viewBounds: {left: 8, top: 32, right: 96, bottom: 48},
     Action:
       func()
       begin
       	:DoEvent('Bind, nil);
       end,
     declareSelf: 'InstantiateSuccess,
     nextState: 'Bind,
     debug: "Instantiate Success",
     _proto: _userproto000
    };
AddStepForm(Instantiate, Instantiate Success);



Instantiate Failure :=
    {viewBounds: {left: 8, top: 48, right: 96, bottom: 64},
     Action:
       func(error)
       begin
       	:MNotifyError("Endpoint Instantiate", error);
       	:DoEvent('CleanUp, nil);
       end,
     declareSelf: 'InstantiateFailure,
     nextState: 'CleanUp,
     debug: "Instantiate Failure",
     _proto: _userproto000
    };
AddStepForm(Instantiate, Instantiate Failure);



Cancel :=
    {viewBounds: {left: 8, top: 64, right: 96, bottom: 80},
     declareSelf: 'Cancel,
     Action:
       func()
       begin
       	// This state doesn't know how to cancel. We assume that there are events
       	// in the queue, or being sent in from outside the FSM that will cause a
       	// transition to a state that does know how to cancel. By resending
       	// the event we eliminate the need to remember that a cancel has been
       	// received. This is a general pattern. If a state doesn't know how to
       	// handle an important event then the event is resent on the assumption
       	// that eventually we'll get to a state that does know how to handle the
       	// event.
       	:DoEvent('Cancel, nil);
       end,
     debug: "Cancel",
     _proto: _userproto000
    };
AddStepForm(Instantiate, Cancel);



Power Off :=
    {viewBounds: {left: 8, top: 80, right: 96, bottom: 96},
     declareSelf: 'PowerOff,
     Action:
       func()
       begin
       	// See the discussion of the Cancel event in Instantiate.Cancel.Action
       	:DoEvent('PowerOff, nil);
       end,
     debug: "Power Off",
     _proto: _userproto000
    };
AddStepForm(Instantiate, Power Off);





Bind :=
    {viewBounds: {left: 120, top: 128, right: 224, bottom: 232},
     declareSelf: 'Bind,
     debug: "Bind",
     _proto: _userproto001
    };
AddStepForm(Drink FSM, Bind);

Bind :=
    {viewBounds: {left: 8, top: 16, right: 96, bottom: 32},
     declareSelf: 'Bind,
     Action:
       func()
       begin
       	fEndpoint:Bind(:MBuildConfigOptions(), fCompletionSpec);
       end,
     fCompletionSpec:
       {	async:					true,
       	reqTimeout:			kNoTimeout,
       	completionScript:	func(ep, options, result)
       								begin
       									if result then
       										ep:DoEvent('BindFailure, [result]);
       									else
       										ep:DoEvent('BindSuccess, nil);
       								end,	},
     MBuildConfigOptions:
       func()
       begin
       	// Add any options needed at bind time here.
       	nil;
       end,
     debug: "Bind",
     _proto: _userproto000
    };
AddStepForm(Bind, Bind);



Bind Success :=
    {viewBounds: {left: 8, top: 32, right: 96, bottom: 48},
     declareSelf: 'BindSuccess,
     Action:
       func()
       begin
       	:DoEvent('Connect, nil);
       end,
     nextState: 'Connect,
     debug: "Bind Success",
     _proto: _userproto000
    };
AddStepForm(Bind, Bind Success);



Bind Failure :=
    {viewBounds: {left: 8, top: 48, right: 96, bottom: 64},
     declareSelf: 'BindFailure,
     Action:
       func(error)
       begin
       	:MNotifyError("Endpoint Bind", error);
       	:DoEvent('Dispose, nil);
       end,
     nextState: 'Dispose,
     debug: "Bind Failure",
     _proto: _userproto000
    };
AddStepForm(Bind, Bind Failure);



Cancel :=
    {viewBounds: {left: 8, top: 64, right: 96, bottom: 80},
     declareSelf: 'Cancel,
     Action:
       func()
       begin
       	// We're cancelling intentionally so any errors that occur due to the cancel
       	// Shouldn't cause notify's
       	fQuiet := true;
       	
       	try
       		fEndpoint:Cancel(nil);
       	onexception |evt.ex.comm| do
       		nil;
       end,
     debug: "Cancel",
     _proto: _userproto000
    };
AddStepForm(Bind, Cancel);



Power Off :=
    {viewBounds: {left: 8, top: 80, right: 96, bottom: 96},
     declareSelf: 'PowerOff,
     Action:
       func()
       begin
       	// We're powering off so cancel everything!
       	:DoEvent('Cancel, nil);
       end,
     debug: "Power Off",
     _proto: _userproto000
    };
AddStepForm(Bind, Power Off);





Connect :=
    {viewBounds: {left: 120, top: 240, right: 224, bottom: 376},
     declareSelf: 'Connect,
     debug: "Connect",
     _proto: _userproto001
    };
AddStepForm(Drink FSM, Connect);

Connect :=
    {viewBounds: {left: 8, top: 16, right: 96, bottom: 32},
     declareSelf: 'Connect,
     Action:
       func()
       begin
       	if fConnectAction = 'Connect then
       		fEndpoint:Connect(:MBuildConnectConfigOptions(), fCompletionSpec_Connect);
       	else
       		fEndpoint:Listen(:MBuildListenConfigOptions(), fCompletionSpec_Listen);
       end,
     fCompletionSpec_Connect:
       {	async:					true,
       	reqTimeout:			kNoTimeout,
       	completionScript:	func(ep, options, result)
       								begin
       									if result then
       										ep:DoEvent('ConnectFailure, [result]);
       									else
       										ep:DoEvent('ConnectSuccess, nil);
       								end,	},
     fCompletionSpec_Listen:
       {	async:					true,
       	reqTimeout:			kNoTimeout,
       	completionScript:	func(ep, options, result)
       								begin
       									if result then
       										ep:DoEvent('ListenFailure, [result]);
       									else
       										ep:DoEvent('ListenSuccess, nil);
       								end,	},
     MBuildListenConfigOptions:
       func()
       begin
       	nil;
       end,
     MBuildConnectConfigOptions:
       func()
       begin
       	fConnectAddress;
       end,
     debug: "Connect",
     _proto: _userproto000
    };
AddStepForm(Connect, Connect);



Connect Success :=
    {viewBounds: {left: 8, top: 32, right: 96, bottom: 48},
     Action:
       func()
       begin
       	fState := 'Connected;
       	:DoEvent('StartProtocol, nil);
       end,
     declareSelf: 'ConnectSuccess,
     nextState: 'Connected,
     debug: "Connect Success",
     _proto: _userproto000
    };
AddStepForm(Connect, Connect Success);



Connect Failure :=
    {viewBounds: {left: 8, top: 48, right: 96, bottom: 64},
     Action:
       func(error)
       begin
       	:MNotifyError("Endpoint Connect", error);
       	
       	:DoEvent('UnBind, nil);
       end,
     declareSelf: 'ConnectFailure,
     nextState: 'UnBind,
     debug: "Connect Failure",
     _proto: _userproto000
    };
AddStepForm(Connect, Connect Failure);



Listen Success :=
    {viewBounds: {left: 8, top: 64, right: 96, bottom: 80},
     Action:
       func()
       begin
       	:DoEvent('Accept, nil);
       end,
     declareSelf: 'ListenSuccess,
     nextState: 'Accept,
     debug: "Listen Success",
     _proto: _userproto000
    };
AddStepForm(Connect, Listen Success);



Listen Failure :=
    {viewBounds: {left: 8, top: 80, right: 96, bottom: 96},
     Action:
       func(error)
       begin
       	:MNotifyError("Endpoint Listen", error);
       
       	:DoEvent('UnBind, nil);
       end,
     declareSelf: 'ListenFailure,
     nextState: 'UnBind,
     debug: "Listen Failure",
     _proto: _userproto000
    };
AddStepForm(Connect, Listen Failure);



Cancel :=
    {viewBounds: {left: 8, top: 96, right: 96, bottom: 112},
     declareSelf: 'Cancel,
     Action:
       func()
       begin
       	fQuiet := true;
       	
       	try
       		fEndpoint:Cancel(nil);
       	onexception |evt.ex.comm| do
       		nil;
       end,
     debug: "Cancel",
     _proto: _userproto000
    };
AddStepForm(Connect, Cancel);



Power Off :=
    {viewBounds: {left: 8, top: 112, right: 96, bottom: 128},
     declareSelf: 'PowerOff,
     Action:
       func()
       begin
       	:DoEvent('Cancel, nil);
       end,
     debug: "Power Off",
     _proto: _userproto000
    };
AddStepForm(Connect, Power Off);





Accept :=
    {viewBounds: {left: 120, top: 384, right: 224, bottom: 488},
     declareSelf: 'Accepting,
     debug: "Accept",
     _proto: _userproto001
    };
AddStepForm(Drink FSM, Accept);

Accept :=
    {viewBounds: {left: 8, top: 16, right: 96, bottom: 32},
     declareSelf: 'Accept,
     Action:
       func()
       begin
       	fEndpoint:Accept(nil, fCompletionSpec);
       end,
     fCompletionSpec:
       {	async:					true,
       	reqTimeout:			kNoTimeout,
       	completionScript:	func(ep, options, result)
       								begin
       									if result then
       										ep:DoEvent('AcceptFailure, [result]);
       									else
       										ep:DoEvent('AcceptSuccess, nil);
       								end,	},
     debug: "Accept",
     _proto: _userproto000
    };
AddStepForm(Accept, Accept);



Accept Success :=
    {viewBounds: {left: 8, top: 32, right: 96, bottom: 48},
     Action:
       func()
       begin
       	fState := 'Connected;
       	:DoEvent('StartProtocol, nil);
       end,
     declareSelf: 'AcceptSuccess,
     nextState: 'Connected,
     debug: "Accept Success",
     _proto: _userproto000
    };
AddStepForm(Accept, Accept Success);



Accept Failure :=
    {viewBounds: {left: 8, top: 48, right: 96, bottom: 64},
     Action:
       func(error)
       begin
       	:MNotifyError("Endpoint Accept", error);
       	
       	:DoEvent('UnBind, nil);
       end,
     declareSelf: 'AcceptFailure,
     nextState: 'UnBind,
     debug: "Accept Failure",
     _proto: _userproto000
    };
AddStepForm(Accept, Accept Failure);



Cancel :=
    {viewBounds: {left: 8, top: 64, right: 96, bottom: 80},
     declareSelf: 'Cancel,
     Action:
       func()
       begin
       	fQuiet := true;
       	
       	try
       		fEndpoint:Cancel(nil);
       	onexception |evt.ex.comm| do
       		nil;
       end,
     debug: "Cancel",
     _proto: _userproto000
    };
AddStepForm(Accept, Cancel);



Power Off :=
    {viewBounds: {left: 8, top: 80, right: 96, bottom: 96},
     declareSelf: 'PowerOff,
     Action:
       func()
       begin
       	:DoEvent('Cancel, nil);
       end,
     debug: "Power Off",
     _proto: _userproto000
    };
AddStepForm(Accept, Power Off);





Connected :=
    {viewBounds: {left: 232, top: 16, right: 336, bottom: 104},
     declareSelf: 'Connected,
     debug: "Connected",
     _proto: _userproto001
    };
AddStepForm(Drink FSM, Connected);

Disconnect :=
    {viewBounds: {left: 8, top: 16, right: 96, bottom: 32},
     Action:
       func()
       begin
       	fState := 'Disconnecting;
       	fQuiet := true;
       	
       	try
       		fEndpoint:Cancel(nil);
       	onexception |evt.ex.comm| do
       		nil;
       	
       	:DoEvent('Disconnect, nil);
       end,
     declareSelf: 'Disconnect,
     nextState: 'Disconnect,
     debug: "Disconnect",
     _proto: _userproto000
    };
AddStepForm(Connected, Disconnect);



Start Protocol :=
    {viewBounds: {left: 8, top: 32, right: 96, bottom: 48},
     Action:
       func()
       begin
       	fEndpoint:SetInputSpec(fEndpoint.fInputCommand);
       end,
     declareSelf: 'StartProtocol,
     nextState: 'Protocol,
     debug: "Start Protocol",
     _proto: _userproto000
    };
AddStepForm(Connected, Start Protocol);



Cancel :=
    {viewBounds: {left: 8, top: 48, right: 96, bottom: 64},
     declareSelf: 'Cancel,
     Action:
       func()
       begin
       	try
       		fEndpoint:Cancel(nil);
       	onexception |evt.ex.comm| do
       		nil;
       	
       	:DoEvent('Disconnect, nil);
       end,
     debug: "Cancel",
     _proto: _userproto000
    };
AddStepForm(Connected, Cancel);



Power Off :=
    {viewBounds: {left: 8, top: 64, right: 96, bottom: 80},
     declareSelf: 'PowerOff,
     Action:
       func()
       begin
       	:DoEvent('Disconnect, nil);
       end,
     debug: "Power Off",
     _proto: _userproto000
    };
AddStepForm(Connected, Power Off);





Disconnect :=
    {viewBounds: {left: 232, top: 112, right: 336, bottom: 216},
     declareSelf: 'Disconnect,
     debug: "Disconnect",
     _proto: _userproto001
    };
AddStepForm(Drink FSM, Disconnect);

Disconnect :=
    {viewBounds: {left: 8, top: 16, right: 96, bottom: 32},
     declareSelf: 'Disconnect,
     Action:
       func()
       begin
       	try
       		fEndpoint:Disconnect(true, fCompletionSpec);
       	onexception |evt.ex| do
       		:DoEvent('DisconnectFailure, [CurrentException()]);
       end,
     fCompletionSpec:
       {	async:					true,
       	reqTimeout:			kNoTimeout,
       	completionScript:	func(ep, options, result)
       								begin
       									if result then
       										ep:DoEvent('DisconnectFailure, [result]);
       									else
       										ep:DoEvent('DisconnectSuccess, nil);
       								end,	},
     debug: "Disconnect",
     _proto: _userproto000
    };
AddStepForm(Disconnect, Disconnect);



Disconnect Success :=
    {viewBounds: {left: 8, top: 32, right: 96, bottom: 48},
     Action:
       func()
       begin
       	:DoEvent('UnBind, nil);
       end,
     declareSelf: 'DisconnectSuccess,
     nextState: 'UnBind,
     debug: "Disconnect Success",
     _proto: _userproto000
    };
AddStepForm(Disconnect, Disconnect Success);



Disconnect Failure :=
    {viewBounds: {left: 8, top: 48, right: 96, bottom: 64},
     Action:
       func(error)
       begin
       	:MNotifyError("Endpoint Disconnect", error);
       
       	:DoEvent('UnBind, nil);
       end,
     declareSelf: 'DisconnectFailure,
     nextState: 'UnBind,
     fCompletionSpec:
       {	async:					true,
       	reqTimeout:			kNoTimeout,
       	completionScript:	func(ep, options, result)
       								begin
       									if result then
       										ep:DoEvent('UnBindFailure, [result]);
       									else
       										ep:DoEvent('UnBindSuccess, nil);
       								end,	},
     debug: "Disconnect Failure",
     _proto: _userproto000
    };
AddStepForm(Disconnect, Disconnect Failure);



Cancel :=
    {viewBounds: {left: 8, top: 64, right: 96, bottom: 80},
     declareSelf: 'Cancel,
     Action:
       func()
       begin
       	fQuiet := true;
       	
       	try
       		fEndpoint:Cancel(nil);
       	onexception |evt.ex.comm| do
       		nil;
       end,
     debug: "Cancel",
     _proto: _userproto000
    };
AddStepForm(Disconnect, Cancel);



Power Off :=
    {viewBounds: {left: 8, top: 80, right: 96, bottom: 96},
     declareSelf: 'PowerOff,
     debug: "Power Off",
     _proto: _userproto000
    };
AddStepForm(Disconnect, Power Off);





UnBind :=
    {viewBounds: {left: 232, top: 224, right: 336, bottom: 328},
     declareSelf: 'UnBind,
     debug: "UnBind",
     _proto: _userproto001
    };
AddStepForm(Drink FSM, UnBind);

UnBind :=
    {viewBounds: {left: 8, top: 16, right: 96, bottom: 32},
     declareSelf: 'UnBind,
     Action:
       func()
       begin
       	try
       		fEndpoint:UnBind(fCompletionSpec);
       	onexception |evt.ex| do
       		:DoEvent('UnBindFailure, [CurrentException()]);
       end,
     fCompletionSpec:
       {	async:					true,
       	reqTimeout:			kNoTimeout,
       	completionScript:	func(ep, options, result)
       								begin
       									if result then
       										ep:DoEvent('UnBindFailure, [result]);
       									else
       										ep:DoEvent('UnBindSuccess, nil);
       								end,	},
     debug: "UnBind",
     _proto: _userproto000
    };
AddStepForm(UnBind, UnBind);



UnBind Success :=
    {viewBounds: {left: 8, top: 32, right: 96, bottom: 48},
     Action:
       func()
       begin
       	:DoEvent('Dispose, nil);
       end,
     declareSelf: 'UnBindSuccess,
     nextState: 'Dispose,
     debug: "UnBind Success",
     _proto: _userproto000
    };
AddStepForm(UnBind, UnBind Success);



UnBind Failure :=
    {viewBounds: {left: 8, top: 48, right: 96, bottom: 64},
     Action:
       func(exception)
       begin
       	:MNotifyError("Endpoint UnBind", exception);
       	
       	:DoEvent('Dispose, nil);
       end,
     declareSelf: 'UnBindFailure,
     nextState: 'Dispose,
     debug: "UnBind Failure",
     _proto: _userproto000
    };
AddStepForm(UnBind, UnBind Failure);



Cancel :=
    {viewBounds: {left: 8, top: 64, right: 96, bottom: 80},
     declareSelf: 'Cancel,
     Action:
       func()
       begin
       	fQuiet := true;
       	
       	try
       		fEndpoint:Cancel(nil);
       	onexception |evt.ex.comm| do
       		nil;
       end,
     debug: "Cancel",
     _proto: _userproto000
    };
AddStepForm(UnBind, Cancel);



Power Off :=
    {viewBounds: {left: 8, top: 80, right: 96, bottom: 96},
     declareSelf: 'PowerOff,
     debug: "Power Off",
     _proto: _userproto000
    };
AddStepForm(UnBind, Power Off);





Dispose :=
    {viewBounds: {left: 232, top: 336, right: 336, bottom: 408},
     declareSelf: 'Dispose,
     debug: "Dispose",
     _proto: _userproto001
    };
AddStepForm(Drink FSM, Dispose);

Dispose :=
    {viewBounds: {left: 8, top: 16, right: 96, bottom: 32},
     Action:
       func()
       begin
       	try
       		fEndpoint:Dispose();
       	onexception |evt.ex| do
       		return :DoEvent('DisposeFailure, [CurrentException()]);
       	
       	:DoEvent('DisposeSuccess, nil);
       end,
     declareSelf: 'Dispose,
     debug: "Dispose",
     _proto: _userproto000
    };
AddStepForm(Dispose, Dispose);



Dispose Success :=
    {viewBounds: {left: 8, top: 32, right: 96, bottom: 48},
     Action:
       func()
       begin
       	:DoEvent('CleanUp, nil);
       end,
     declareSelf: 'DisposeSuccess,
     nextState: 'CleanUp,
     debug: "Dispose Success",
     _proto: _userproto000
    };
AddStepForm(Dispose, Dispose Success);



Dispose Failure :=
    {viewBounds: {left: 8, top: 48, right: 96, bottom: 64},
     Action:
       func(error)
       begin
       	:MNotifyError("Endpoint Dispose", error);
       	
       	:DoEvent('CleanUp, nil);
       end,
     declareSelf: 'DisposeFailure,
     nextState: 'CleanUp,
     debug: "Dispose Failure",
     _proto: _userproto000
    };
AddStepForm(Dispose, Dispose Failure);





Clean Up :=
    {viewBounds: {left: 232, top: 416, right: 336, bottom: 456},
     declareSelf: 'CleanUp,
     debug: "Clean Up",
     _proto: _userproto001
    };
AddStepForm(Drink FSM, Clean Up);

Clean Up :=
    {viewBounds: {left: 8, top: 16, right: 96, bottom: 32},
     Action:
       func()
       begin
       	if fPowerOffState then
       		begin
       			fPowerOffState := nil;
       			PowerOffResume(kAppSymbol);
       		end;
       	UnRegPowerOff(kAppSymbol);
       	
       	fEndpoint := nil;
       	fQuiet := nil;
       	fState := 'Disconnected;
       	fConnectAction := nil;
       end,
     declareSelf: 'CleanUp,
     nextState: 'Genesis,
     debug: "Clean Up",
     _proto: _userproto000
    };
AddStepForm(Clean Up, Clean Up);





Protocol :=
    {viewBounds: {left: 344, top: 16, right: 448, bottom: 352},
     declareSelf: 'Protocol,
     debug: "Protocol",
     _proto: _userproto001
    };
AddStepForm(Drink FSM, Protocol);

Drink Begin :=
    {viewBounds: {left: 8, top: 16, right: 96, bottom: 32},
     declareSelf: 'DrinkBegin,
     Action:
       func(data)
       begin
       	local soupName := SubStr(data, 4, StrLen(data) - 5);
       	
       	fSoup := GetUnionSoup(soupName);
       	
       	if not fSoup then
       		return :MMessage("Unknown Soup Requested: " & soupName);
       	
       	:MMessage("Open Soup: " & soupName);
       	
       	fSoupCursor := fSoup:Query(nil);
       	fSoupEntry := fSoupCursor:Entry();
       	
       	fFrameCount := 0;
       	fEndpoint:Output("DRNK", nil, fCompletionSpec);		// tell the server we can do a drink
       end,
     fCompletionSpec:
       {	async:					true,
       	reqTimeout:			kNoTimeout,
       	completionScript:	func(ep, options, result)
       								begin
       									if result then
       										ep:DoEvent('DrinkFailure, [result]);
       									else
       										ep:DoEvent('DrinkSendCommand, nil);
       								end,	},
     debug: "Drink Begin",
     _proto: _userproto000
    };
AddStepForm(Protocol, Drink Begin);



Drink Send Command :=
    {viewBounds: {left: 8, top: 32, right: 96, bottom: 48},
     declareSelf: 'DrinkSendCommand,
     Action:
       func()
       begin
       	fEndpoint:Output("ENTR", nil, fCompletionSpec);		// tell the server we are sending a soup entry
       end,
     fCompletionSpec:
       {	async:					true,
       	reqTimeout:			kNoTimeout,
       	completionScript:	func(ep, options, result)
       								begin
       									if result then
       										ep:DoEvent('DrinkFailure, [result]);
       									else
       										ep:DoEvent('DrinkSendEntry, nil);
       								end,	},
     debug: "Drink Send Command",
     _proto: _userproto000
    };
AddStepForm(Protocol, Drink Send Command);



Drink Send Entry :=
    {viewBounds: {left: 8, top: 48, right: 96, bottom: 64},
     declareSelf: 'DrinkSendEntry,
     Action:
       func()
       begin
       	fEndpoint:Output(fSoupEntry, nil, fCompletionSpec);
       end,
     fCompletionSpec:
       {	async:					true,
       	reqTimeout:			kNoTimeout,
       	form:					'frame,
       	completionScript:	func(ep, options, result)
       								begin
       									if result then
       										ep:DoEvent('DrinkFailure, [result]);
       								end,	},
     debug: "Drink Send Entry",
     _proto: _userproto000
    };
AddStepForm(Protocol, Drink Send Entry);



Drink Next Entry :=
    {viewBounds: {left: 8, top: 64, right: 96, bottom: 80},
     declareSelf: 'DrinkNextEntry,
     Action:
       func()
       begin
       	fFrameCount := fFrameCount + 1;
       	:MMessage("Frame Sent: " & NumberStr(fFrameCount));
       	
       	if fSoupEntry := fSoupCursor:Next() then
       		return :DoEvent('DrinkSendCommand, nil);
       	
       	try
       		fEndpoint:Cancel(nil);
       	onexception |evt.ex.comm| do
       		nil;
       	
       	fEndpoint:SetInputSpec(fEndpoint.fInputCommand);
       	:DoEvent('DrinkEnd, nil);
       end,
     debug: "Drink Next Entry",
     _proto: _userproto000
    };
AddStepForm(Protocol, Drink Next Entry);



Drink End :=
    {viewBounds: {left: 8, top: 80, right: 96, bottom: 96},
     declareSelf: 'DrinkEnd,
     Action:
       func()
       begin
       	fEndpoint:Output("END ", nil, fCompletionSpec);
       end,
     fCompletionSpec:
       {	async:					true,
       	reqTimeout:			kNoTimeout,
       	completionScript:	func(ep, options, result)
       								begin
       									if result then
       										ep:DoEvent('DrinkFailure, [result]);
       									else
       										ep:DoEvent('DrinkSuccess, nil);
       								end,	},
     debug: "Drink End",
     _proto: _userproto000
    };
AddStepForm(Protocol, Drink End);



Drink Success :=
    {viewBounds: {left: 8, top: 96, right: 96, bottom: 112},
     declareSelf: 'DrinkSuccess,
     Action:
       func()
       begin
       	:MMessage("All Frames Sent");
       	:DoEvent('Disconnect, nil);
       end,
     nextState: 'Connected,
     debug: "Drink Success",
     _proto: _userproto000
    };
AddStepForm(Protocol, Drink Success);



Drink Failure :=
    {viewBounds: {left: 8, top: 112, right: 96, bottom: 128},
     declareSelf: 'DrinkFailure,
     Action:
       func(error)
       begin
       	:MNotifyError("Drink Failure", error);
       	
       	:DoEvent('Disconnect, nil);
       end,
     nextState: 'Connected,
     debug: "Drink Failure",
     _proto: _userproto000
    };
AddStepForm(Protocol, Drink Failure);



Hello Begin :=
    {viewBounds: {left: 8, top: 136, right: 96, bottom: 152},
     declareSelf: 'HelloBegin,
     Action:
       func(data)
       begin
       	fEndpoint:Output("Hello", nil, fCompletionSpec);
       end,
     fCompletionSpec:
       {	async:					true,
       	reqTimeout:			kNoTimeout,
       	completionScript:	func(ep, options, result)
       								begin
       									if result then
       										ep:DoEvent('HelloFailure, [result]);
       									else
       										ep:DoEvent('HelloSuccess, nil);
       								end,	},
     debug: "Hello Begin",
     _proto: _userproto000
    };
AddStepForm(Protocol, Hello Begin);



Hello Success :=
    {viewBounds: {left: 8, top: 152, right: 96, bottom: 168},
     declareSelf: 'HelloSuccess,
     Action:
       func()
       begin
       	:MMessage("Hello, DILette... pleased to meet you!");
       	:DoEvent('Disconnect, nil);
       end,
     nextState: 'Connected,
     debug: "Hello Success",
     _proto: _userproto000
    };
AddStepForm(Protocol, Hello Success);



Hello Failure :=
    {viewBounds: {left: 8, top: 168, right: 96, bottom: 184},
     declareSelf: 'HelloFailure,
     Action:
       func(result)
       begin
       	:MNotifyError("Hello Failure", error);
       	
       	:DoEvent('Disconnect, nil);
       end,
     nextState: 'Connected,
     debug: "Hello Failure",
     _proto: _userproto000
    };
AddStepForm(Protocol, Hello Failure);



Name Begin :=
    {viewBounds: {left: 8, top: 192, right: 96, bottom: 208},
     declareSelf: 'NameBegin,
     Action:
       func(data)
       begin
       	if fSoup := GetUnionSoup("Names") then
       		return :MMessage("Open Names Soup");
       	
       	:MMessage("Names soup doesn't exist?!");
       	:DoEvent('Cancel, nil);
       end,
     debug: "Name Begin",
     _proto: _userproto000
    };
AddStepForm(Protocol, Name Begin);



Name Add :=
    {viewBounds: {left: 8, top: 208, right: 96, bottom: 224},
     declareSelf: 'NameAdd,
     Action:
       func(data)
       begin
       	fSoup:AddToStoreFlushedXmit(data, GetDefaultStore(), kAppSymbol);
       	
       	fEndpoint:Output("OK", nil, fCompletionSpec);
       end,
     fCompletionSpec:
       {	async:					true,
       	reqTimeout:			kNoTimeout,
       	completionScript:	func(ep, options, result)
       								begin
       									if result then
       										ep:DoEvent('NameFailure, [result]);
       									else
       										ep:DoEvent('NameSuccess, nil);
       								end,	},
     debug: "Name Add",
     _proto: _userproto000
    };
AddStepForm(Protocol, Name Add);



Name Success :=
    {viewBounds: {left: 8, top: 224, right: 96, bottom: 240},
     declareSelf: 'NameSuccess,
     Action:
       func()
       begin
       	:MMessage("Frame added.");
       	:DoEvent('Disconnect, nil);
       end,
     nextState: 'Connected,
     debug: "Name Success",
     _proto: _userproto000
    };
AddStepForm(Protocol, Name Success);



Name Failure :=
    {viewBounds: {left: 8, top: 240, right: 96, bottom: 256},
     declareSelf: 'NameFailure,
     Action:
       func(error)
       begin
       	:MNotifyError("Name Failure", error);
       	
       	:DoEvent('Disconnect, nil);
       end,
     nextState: 'Connected,
     debug: "Name Failure",
     _proto: _userproto000
    };
AddStepForm(Protocol, Name Failure);



Unknown :=
    {viewBounds: {left: 8, top: 264, right: 96, bottom: 280},
     declareSelf: 'Unknown,
     Action:
       func(data)
       begin
       	:MMessage("Unknown Command Received: " & data);
       	:DoEvent('Disconnect, nil);
       end,
     nextState: 'Connected,
     debug: "Unknown",
     _proto: _userproto000
    };
AddStepForm(Protocol, Unknown);



Input Failure :=
    {viewBounds: {left: 8, top: 280, right: 96, bottom: 296},
     declareSelf: 'InputFailure,
     Action:
       func(error)
       begin
       	:MNotifyError("Input Failure", error);
       	
       	:DoEvent('Disconnect, nil);
       end,
     nextState: 'Connected,
     debug: "Input Failure",
     _proto: _userproto000
    };
AddStepForm(Protocol, Input Failure);



Cancel :=
    {viewBounds: {left: 8, top: 296, right: 96, bottom: 312},
     declareSelf: 'Cancel,
     Action:
       func()
       begin
       	fQuiet := true;
       	
       	try
       		fEndpoint:Cancel(nil);
       	onexception |evt.ex.comm| do
       		nil;
       
       	:DoEvent('Disconnect, nil);
       end,
     nextState: 'Connected,
     debug: "Cancel",
     _proto: _userproto000
    };
AddStepForm(Protocol, Cancel);



Power Off :=
    {viewBounds: {left: 8, top: 312, right: 96, bottom: 328},
     declareSelf: 'PowerOff,
     Action:
       func()
       begin
       	:DoEvent('Cancel, nil);
       end,
     debug: "Power Off",
     _proto: _userproto000
    };
AddStepForm(Protocol, Power Off);





// After Script for "Drink FSM"
thisView := Drink FSM;
call kFSMCleanUpFunc with (thisView);


constant |layout_DrinkFSM| := Drink FSM;
// End of file DrinkFSM
// Beginning of file Main.t

// Before Script for "SoupDrink"
// By Rob Langhorne, Christopher Bell, David Fedor, Jim Schram and Bruce Thompson
// Copyright Apple Computer, Inc. 1995-1996.  All rights reserved.


SoupDrink :=
    {
     MMessage:
       func(message)
       begin
       	if kDebugOn then
       		AddArraySlot(GetRoot().(kAppSymbol).fStatusMessages, message);
       	
       	if call kViewIsOpenFunc with (GetRoot().(kAppSymbol)) then
       		begin
       			SetValue(GetRoot().(kAppSymbol).vStatusArea, 'text, message);
       			RefreshViews();
       		end;
       end,
     viewQuitScript:
       func()
       begin
       	// Tell the FSM to shut down.
       	fFSM:DoEvent('Cancel, nil);
       	fFSM:DoEvent('Disconnect, nil);
       end,
     fStatusMessages: nil,
     viewBounds: {left: 0, top: 0, right: 240, bottom: 330},
     fFSM: nil,
     title: kAppName,
     viewSetupFormScript:
       func()
       begin
       	local box := GetAppParams();
       	viewBounds := RelBounds(	box.appAreaLeft,
       											box.appAreaTop,
       									Min(	box.appAreaWidth,	240	),
       									Min(	box.appAreaHeight,	336	)	);
       	
       	if kDebugOn then
       		fStatusMessages := [];
       	
       	// Create the FSM
       	fFSM := GetLayout("DrinkFSM"):Instantiate();
       	
       	// Provide parent inheritance for the FSM.
       	fFSM._parent := self;
       end,
     viewSetupDoneScript:
       func()
       begin
          :MMessage("Ready to connect");
       end,
     fNBPType: "SoupDrink",
     debug: "SoupDrink",
     _proto: @157
    };

vStatusArea :=
    {text: "",
     viewBounds: {left: 12, top: 48, right: 227, bottom: 123},
     viewJustify: 0,
     viewFormat: 67436880,
     viewFont: simpleFont18,
     debug: "vStatusArea",
     _proto: @218
    };
AddStepForm(SoupDrink, vStatusArea);
StepDeclare(SoupDrink, vStatusArea, 'vStatusArea);



vConnectionType :=
    {viewBounds: {left: 42, top: 134, right: 114, bottom: 178},
     viewSetupDoneScript:
       func()
       begin
       	:SetClusterValue('SerialMNP);
       end,
     clusterValue: 'SerialMNP,
     debug: "vConnectionType",
     _proto: @203
    };
AddStepForm(SoupDrink, vConnectionType);
StepDeclare(SoupDrink, vConnectionType, 'vConnectionType);

SerialMNP :=
    {buttonValue: 'SerialMNP,
     viewBounds: {left: 4, top: 4, right: 68, bottom: 20},
     text: "Serial MNP",
     debug: "SerialMNP",
     _proto: @202
    };
AddStepForm(vConnectionType, SerialMNP);



ADSP :=
    {buttonValue: 'ADSP,
     viewBounds: {left: 4, top: 24, right: 68, bottom: 40},
     text: "ADSP",
     debug: "ADSP",
     _proto: @202
    };
AddStepForm(vConnectionType, ADSP);





vConnect :=
    {text: "Connect",
     buttonClickScript:
       func()
       begin
       	// Ignore if the FSM is already active.
       	if not fFSM.fState
       	or fFSM.fState = 'Disconnected then
       		begin
       			fStatusMessages := [];
       			if vConnectionType.clusterValue = 'ADSP then
       				GetRoot().NetChooser:OpenNetChooser(	nil,
       																			"=:" & fNBPType & "@",
       																			nil,
       																			self,
       																			"Connect",
       																			"SoupDrink Server",
       																			"SoupDrink Servers");
       			else
       				// Connect using SerialMNP
       				fFSM:DoEvent('Create, [vConnectionType.clusterValue, nil]);
       		end;
       end,
     viewBounds: {left: 124, top: 136, right: 196, bottom: 152},
     NetworkChooserDone:
       func(selection, zone)
       begin
       	if selection then
       	// Connect using ADSP
       		fFSM:DoEvent('Create, [vConnectionType.clusterValue, MakeAppleTalkOption(selection & ":" & fNBPtype & "@" & (if zone then zone else "*"))]);
       end,
     debug: "vConnect",
     _proto: @226
    };
AddStepForm(SoupDrink, vConnect);
StepDeclare(SoupDrink, vConnect, 'vConnect);



vDisconnect :=
    {text: "Disconnect",
     buttonClickScript:
       func()
       begin
       	// Ignore if the FSM isn't connected.
       	if fFSM.fState = 'Connected then
       		fFSM:DoEvent('Cancel, nil);
       end,
     viewBounds: {left: 124, top: 160, right: 196, bottom: 176},
     debug: "vDisconnect",
     _proto: @226
    };
AddStepForm(SoupDrink, vDisconnect);
StepDeclare(SoupDrink, vDisconnect, 'vDisconnect);



vTraceBox :=
    {text: "",
     viewBounds: {left: 12, top: 192, right: 228, bottom: 264},
     viewJustify: 0,
     viewFont: simpleFont9,
     debug: "vTraceBox",
     _proto: @218
    };
AddStepForm(SoupDrink, vTraceBox);
StepDeclare(SoupDrink, vTraceBox, 'vTraceBox);




constant |layout_Main.t| := SoupDrink;
// End of file Main.t



